﻿using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.MediaLibrary.Models;
using Orchard.MediaLibrary.Services;
using PlanetTelex.Coverflow.Models;
using PlanetTelex.Coverflow.Utilities;

namespace PlanetTelex.Coverflow.Services
{
    public class CoverflowService : ICoverflowService
    {
        private readonly StringUtility _stringUtility = new StringUtility();
        private readonly IList<string> _allowedFileFormats = new[] { "bmp", "gif", "png", "jpg", "jpeg", "tiff" };
        private readonly IMediaLibraryService _mediaLibraryService;

        public const string SelectFolder = "-- Select Folder --";

        public CoverflowService(IMediaLibraryService mediaLibraryService)
        {
            _mediaLibraryService = mediaLibraryService;
        }
        
        #region Implementation of ICoverflowService

        public IEnumerable<string> AllowedFileFormats
        {
            get { return _allowedFileFormats; }
        }

        public IEnumerable<IMediaFolder> ListAllMediaFolders()
        {
            return GetFoldersRecursive();
        }

        public IEnumerable<IMediaFolder> ListSubFolders(string basePath)
        {
            try
            {
                return _mediaLibraryService.GetMediaFolders(basePath);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public IEnumerable<MediaFile> ListMediaFolderContents(string basePath)
        {
            try
            {
                return _mediaLibraryService.GetMediaFiles(basePath).Where(o => AllowedFileFormats.Contains(o.Name.Split('.').Last().ToLower()));
            }
            catch (Exception)
            {
                return null;
            }
        }

        public List<Cover> ListAllCovers(string basePath, bool categoriesEnabled)
        {
            var returnVal = new List<Cover>();
            basePath = basePath ?? string.Empty;

            if (categoriesEnabled)
                foreach (IMediaFolder mediaFolder in ListSubFolders(basePath))
                    returnVal.AddRange(ListAllCovers(mediaFolder.MediaPath, false));
            
            
            if (!string.IsNullOrWhiteSpace(basePath))
            {
                var mediaFiles = ListMediaFolderContents(basePath);
                if (mediaFiles != null)
                {
                    returnVal.AddRange(mediaFiles.Select(mediaFile => new Cover
                        {
                            ImagePath = GetUrl(basePath, mediaFile.Name),
                            Category = FormatMediaNameForDisplay(mediaFile.FolderName),
                            Title = GetTitleFromName(mediaFile.Name),
                            Subtitle = GetSubtitleFromName(mediaFile.Name)
                        }));
                }
            }
            return returnVal;
        }

        public string GetUrl(string basePath, string filename)
        {
            return !string.IsNullOrEmpty(basePath) ? _mediaLibraryService.GetMediaPublicUrl(basePath, filename) : string.Empty;
        }

        #endregion

        private string GetTitleFromName(string fileName)
        {
            var title = fileName.Split('_')[0];
            return FormatMediaNameForDisplay(title);
        }

        private string GetSubtitleFromName(string fileName)
        {
            var titleSplit = fileName.Split('_');
            if (titleSplit.Count() == 1)
                return string.Empty;

            return FormatMediaNameForDisplay(titleSplit[1]);
        }

        private string FormatMediaNameForDisplay(string toFormat)
        {
            var returnVal = string.Empty;
            var pathSplit = toFormat.Split('\\');
            var periodSplit = pathSplit[pathSplit.Length - 1].Split('.');
            
            for(var i = 0; i < Math.Max(periodSplit.Length - 1, 1); i++)
                returnVal += periodSplit[i].Replace('-', ' ').Replace('_', ' ').Trim() + "-";
            
            returnVal = _stringUtility.RemoveLeadingNumbers(returnVal).TrimEnd('-'); // Remove leading numbers which can be used to specify the order of the covers.
            return _stringUtility.TitleCase(returnVal); // Don't force lowercase so specific casing is persisted.
        }

        private IEnumerable<IMediaFolder> GetFoldersRecursive()
        {
            var allMediaFolders = new List<IMediaFolder> { new MediaFolder { MediaPath = SelectFolder }};
            GetFoldersAtPath(string.Empty, allMediaFolders);
            return allMediaFolders;
        }

        private void GetFoldersAtPath(string path, List<IMediaFolder> allFolders)
        {
            var folders = _mediaLibraryService.GetMediaFolders(path);
            foreach (var mediaFolder in folders)
            {
                allFolders.Add(mediaFolder);
                GetFoldersAtPath(mediaFolder.MediaPath, allFolders);
            }
        }
    }
}
